package base.file_io_demo.io_demo01;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class FileUtil {
	
	public static void main(String[] args) {
		// 文件到文件
//		try {
//			InputStream in = new FileInputStream("files/source/80MGBK.txt");
//			OutputStream out = new FileOutputStream("files/target/80MGBK-copy.txt");
//			//copy2(in, out);
//		    copy(in, out);// 高效
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
		
		
		byte[] datas = null;
		// 文件到字节数组
		try {
			InputStream in = new FileInputStream("files/source/80MGBK.txt");
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			long t1 = System.currentTimeMillis();
			//copy2(in, out);
			copy(in, out); // 高效，提升近1倍
			long t2 = System.currentTimeMillis();
			System.out.println(t2-t1);
			datas = out.toByteArray();
			System.out.println(datas.length);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
		// 字节数组到文件
		try {
			OutputStream out = new FileOutputStream("files/target/80MGBK-copy.txt");
			InputStream in = new ByteArrayInputStream(datas);
			long t1 = System.currentTimeMillis();
			//copy2(in, out);
			copy(in, out);// 高效，提升5倍
			long t2 = System.currentTimeMillis();
			System.out.println(t2-t1);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Deprecated
	public static void copy2(InputStream in, OutputStream out) {
		try(InputStream input = in; 
				OutputStream output = out) {
			byte[] buff = new byte[1024]; // 定义一容器
			int len = -1; // 每次实际读取字节长度
			while(-1 != (len = input.read(buff))) {
				output.write(buff, 0, len);
			}
			output.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 功能：实现对任何文件的拷贝（图像、文本、GBK类型文件、办公文件doc等的拷贝）
	 * 使用缓冲流这个处理流包装处理下，以便于提高效率
	 */
	public static void copy(InputStream in, OutputStream out) {
		try(InputStream input = new BufferedInputStream(in);
				OutputStream output = new BufferedOutputStream(out)){
			byte[] buff = new byte[1024];
			int len = -1;
			while(-1 != (len=input.read(buff))) {
				output.write(buff, 0, len);
			}
			output.flush();
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 功能：实现对字符文件的拷贝
	 */
	public static void copyTxt(String src, String dest) {
		try(BufferedReader reader = new BufferedReader(new FileReader(src));
				BufferedWriter writer = new BufferedWriter(new FileWriter(dest))){
			String line = null;
			while(null != (line=reader.readLine())) {
				writer.write(line);
				writer.newLine();
			}
			writer.flush();
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 功能：将网页源码下载到本地
	 * @param url 限制性网页地址
	 * @param file  保存成本地文件名
	 */
	public static void downloadNetToFile(String url, String file) {
		try (BufferedReader reader = 
				new BufferedReader(
						new InputStreamReader(
//								new URL("http://www.baidu.com").openStream(),"UTF-8"));//指定每读取3个字节转换为一个字符
								new URL(url).openStream(),"UTF-8"));
			 BufferedWriter writer = 
					 new BufferedWriter(
							 new OutputStreamWriter(
//									 new FileOutputStream("files/target/baidu.txt"),"UTF-8"))){//指定写成UTF-8编码文件
									 new FileOutputStream(file),"UTF-8"))){
			String line = null;
			while(null != (line=reader.readLine())) {
				writer.write(line);
				writer.newLine();
			}
			writer.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 功能：对限制性网页源码进行下载。有些网站限制了程序对其源码进行下载，此时可以模拟浏览器发起访问。
	 * @param url 限制性网页地址
	 * @param file  保存成本地文件名
	 * @throws IOException 
	 * @throws MalformedURLException 
	 */
	public static void downloadNetToFile(String url, String file, String method, String charsetName) throws Exception {
		HttpURLConnection connection = (HttpURLConnection)new URL(url).openConnection();
//		connection.setRequestMethod("GET");
		connection.setRequestMethod(method);
		connection.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36");
		try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),charsetName));
//				BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file),"UTF-8"))){
				BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file),charsetName))){
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void close(Closeable... ios) {
		for(Closeable io:ios) {
			try {
				if(io != null) {
					io.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void deleteAllFiles(File file) {
		if(!file.exists()) {
			throw new RuntimeException("文件不存在");
		}
		if(file.isFile() || file.list().length==0) {//如果虚拟对象file是文件或者空的目录,就删除
			file.delete();
		}else {
			File[] files = file.listFiles();
			for(File f : files) {
				deleteAllFiles(f);
			}
			file.delete();// 删除file文件夹
		}
	}
	
	/**
	 * 采用try...with....resource 这种格式，jdk7会自动释放流资源
	 * 功能：读取文件到字节数组
	 * 内部采用InputStream 字节流形式，不存在乱码问题，可以处理图像和文本数据
	 */
	public static byte[] fileToByteArray(String file) {
		
		try(InputStream input = new FileInputStream(file);
			ByteArrayOutputStream out = new ByteArrayOutputStream();) {
			
			byte[] buff = new byte[1024*10];// 要保证程序可读性采用10*1024写法
			int len = -1;
			while(-1 != (len = input.read(buff))) {
				out.write(buff, 0, len);
			}
			out.flush();
			return out.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 采用try...with....resource 这种格式，jdk7会自动释放流资源
	 * 功能：字节数组写出到文件
	 * 内部采用OutputStream 字节流形式，不存在乱码问题，可以处理图像和文本数据
	 */
	public static void byteArrayToFile(byte[] dest, String file) {
		
		try(OutputStream out =new FileOutputStream(file);
			ByteArrayInputStream input = new ByteArrayInputStream(dest);) {
			
			byte[] buff = new byte[1024];
			int len = -1;
			while(-1 != (len = input.read(buff))) {
				out.write(buff, 0, len);
			}
			out.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
